#include "HTTPDownload.h"

#include "NetworkAccessManager.h"

//#include <QtCore>
#include <QtNetwork>
#include <QDir>



HTTPDownload::HTTPDownload(QObject *parent) :
    QObject(parent)
{
    m_bHttpDownloadRunning = false;

    connect(NetworkAccessManager::instance(), SIGNAL(finished(QNetworkReply*)), this, SLOT(onFinished(QNetworkReply*)));
//    connect(NetworkAccessManager::instance(), &QNetworkAccessManager::finished, this, [=] {
//        qDebug() << "!!!!!!!!!!!!!yeah";
//    });
}

HTTPDownload::~HTTPDownload()
{

}

bool HTTPDownload::checkURL(QUrl url)
{
    if (!url.isValid())
    {
        qCritical() << "[!HTTPDownload]ERROR:Invalid URL:" << url;
        return false;
    }

    if (url.scheme() == "http" || url.scheme() == "https")
    {
        if(url.scheme() == "https")
        {
            QSslConfiguration config = m_NetWorkRequest.sslConfiguration();
            config.setPeerVerifyMode(QSslSocket::VerifyNone);
            config.setProtocol(QSsl::SecureProtocols);
            m_NetWorkRequest.setSslConfiguration(config);
        }
    }
    else
    {
        qCritical() << "[!HTTPDownload]ERROR:URL must start with 'http/https:':" << url.scheme();
        return false;
    }

    if (url.path().isEmpty())   //必须要有路径（哪怕是单个/）
    {
        qCritical() << "[!HTTPDownload]ERROR:URL has no path!";
        return false;
    }
    //url.host(), url.port(80)

    return true;
}

int HTTPDownload::download(QUrl url, QString localpathfile, bool writeToFile)
{
    if(NetworkAccessManager::instance()->networkAccessible() != QNetworkAccessManager::Accessible)
        return -1;

    if(m_bHttpDownloadRunning == true)
        return -2;

    if(!checkURL(url))
        return -3;


    if(writeToFile)     //写入文件
    {
        m_nWriteType = 1;

        QFileInfo fileInfo = "." + url.path();
        //file = new QFile(fileInfo.fileName());

        if(localpathfile.isEmpty())
            m_strLocalFilePathName = fileInfo.absoluteFilePath(); // QFileInfo(url.path()).fileName();
        else
        {
            m_strLocalFilePathName = localpathfile;
            fileInfo.setFile(m_strLocalFilePathName);
        }

        if (m_strLocalFilePathName.isEmpty())
        {
            m_strLocalFilePathName = "HTTPDownload.out";
            fileInfo.setFile(m_strLocalFilePathName);
        }


/*
        qDebug() << "path:" << url.path();
        qDebug() << "filePath:" << fileInfo.filePath();
        qDebug() << "absoluteFilePath:" << fileInfo.absoluteFilePath();
        qDebug() << "canonicalFilePath:" << fileInfo.canonicalFilePath();
        qDebug() << "baseName:" << fileInfo.baseName();
        qDebug() << "completeBaseName:" << fileInfo.completeBaseName();
        qDebug() << "suffix:" << fileInfo.suffix();
        qDebug() << "bundleName:" << fileInfo.bundleName();
        qDebug() << "completeSuffix:" << fileInfo.completeSuffix();
        qDebug() << "path:" << fileInfo.path();
        qDebug() << "absolutePath:" << fileInfo.absolutePath();
        qDebug() << "canonicalPath:" << fileInfo.canonicalPath();
        qDebug() << "dir:" << fileInfo.dir();
        qDebug() << "absoluteDir:" << fileInfo.absoluteDir();
*/

        //创建目录
        QString m_strDir = fileInfo.absolutePath();//文件的存储位置
        if( !m_strDir.isEmpty() )//文件夹
        {
            QDir directory( m_strDir );
            if( !directory.exists() )//没有此文件夹，则创建
            {
                if(!directory.mkpath( m_strDir ))
                {
                    qCritical() << "[!HTTPDownload]ERROR:Fail to make path!";
                    return -4;
                }
            }
            //m_strFileName = m_strDir + "/"+m_strFileName;//添加/是为了防止用户名没有加/，因为对于文件夹来说两个/都会当成一个/
        }


        //写到临时文件
        qDebug() << "File Create:" << m_strLocalFilePathName + ".tmp";

        m_fileOut.setFileName(m_strLocalFilePathName + ".tmp");
        if(!m_fileOut.open(QIODevice::WriteOnly))    //只读方式打开文件
        {
            qCritical() << "[!HTTPDownload]ERROR:Fail to save file!";
            return -5;
        }

        qDebug() << "[HTTPDownload]Download filepath:" << m_strDir;

    }
    else    //写到m_baHttpData
    {
        m_baHttpData.clear();
        m_nWriteType = 0;
    }



    //开始提交URL
    m_NetWorkRequest.setUrl(url);
    /******************设置http的header***********************/
    // request.setHeader(QNetworkRequest::ContentTypeHeader, "multipart/form-data");
    // request.setHeader(QNetworkRequest::ContentTypeHeader, "application/octet-stream");
    // request.setRawHeader("Content-Disposition","form-data;name='doc';filename='a.txt'");
    // request.setHeader(QNetworkRequest::ContentLengthHeader,post_data.length());
    m_NetWorkRequest.setRawHeader("User-Agent", "HTTPDownload by Leamus");

    qDebug() << "[HTTPDownload]Request Header:" << m_NetWorkRequest.rawHeaderList();


    m_pNetWorkReply = NetworkAccessManager::instance()->get(m_NetWorkRequest);      //通过发送数据，返回值保存在reply指针里.

    connect(m_pNetWorkReply, SIGNAL(downloadProgress(qint64,qint64)), this, SLOT( onDownloadProgress(qint64, qint64)));//download文件时进度
    connect(m_pNetWorkReply, SIGNAL(readyRead()),this, SLOT(onReadyRead()));
    connect(m_pNetWorkReply, SIGNAL(error(QNetworkReply::NetworkError)),this, SLOT( onReplyError(QNetworkReply::NetworkError)) );//出现错误时发送此信号;
    connect(m_pNetWorkReply, &QNetworkReply::sslErrors, this, &HTTPDownload::onReplySslErrors);
    connect(m_pNetWorkReply, &QNetworkReply::finished, this, [=]{
        qDebug() << "[HTTPDownload]m_pNetWorkReply finished";
        //onFinished(m_pNetWorkReply);
    });



    m_bHttpDownloadRunning = true;

    return 0;
}

void HTTPDownload::onReadyRead()
{
    if(QNetworkReply::NoError == m_pNetWorkReply->error())
    {
        qDebug() << "[HTTPDownload]onReadyRead: NoError";

        if(m_nWriteType == 1)  //写到文件
            m_fileOut.write(m_pNetWorkReply->readAll());
        else
            m_baHttpData.append(m_pNetWorkReply->readAll());
    }
    else
    {
        qCritical() << "[!HTTPDownload]onReadyRead ERROR:" << m_pNetWorkReply->error();
        //stop();
    }

    //qDebug() << m_baHttpData;
    qDebug() << "[HTTPDownload]sender:" << this->sender() << m_pNetWorkReply;
}


/***************响应结束**************************/
void HTTPDownload::onFinished(QNetworkReply *reply)
{
    if(m_nWriteType == 1)
    {
        if(m_fileOut.isOpen())
        {
            m_fileOut.flush();
            m_fileOut.close();
        }
        else
        {
            reply->deleteLater();
            m_bHttpDownloadRunning = false;
            qCritical() << "[!HTTPDownload]ERROR:Save File failed:" << m_strLocalFilePathName + ".tmp";
            emit s_finished(1, QNetworkReply::NoError, 1);
            return;
        }
    }


    //获取响应的信息，状态码为200表示正常
    QVariant status_code = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);

    //无错误返回
    if(QNetworkReply::NoError == reply->error() && 200 == status_code)
    {
        if(m_nWriteType == 1)   //如果保存到文件，则将tmp文件重命名替换至源文件
        {
            if( QFile::exists(m_strLocalFilePathName) )//如果文件已经存在，那么删除
            {
                if(!QFile::remove(m_strLocalFilePathName))  //如果删除失败，则另存为old文件
                {
                    if(!QFile::rename(m_strLocalFilePathName, "~" + m_strLocalFilePathName + ".old"))
                        qWarning() << "[!HTTPDownload]Delete Old File Fail!";
                }
            }
            if(!QFile::rename(m_strLocalFilePathName + ".tmp", m_strLocalFilePathName))
            {
                reply->deleteLater();
                m_bHttpDownloadRunning = false;
                qCritical() << "[!HTTPDownload]Rename File ERROR!";
                emit s_finished(1, QNetworkReply::NoError, 2);
                return;
            }
        }

        qDebug() << "[HTTPDownload]Your thing had finished downloading.";
        emit s_finished(0, reply->error(), status_code.toInt());
    }
    else
    {
        if(m_nWriteType == 1)
        {
            if( QFile::exists(m_strLocalFilePathName + ".tmp") )//如果文件已经存在，那么删除
            {
                if(!QFile::remove(m_strLocalFilePathName + ".tmp"))
                    qCritical() << "[!HTTPDownload]Remove Temp File ERROR!";
            }
        }

        //处理错误
        qCritical() << "[!HTTPDownload]Download ERROR:" << status_code << reply->error();
        emit s_finished(0, reply->error(), status_code.toInt());
    }


    m_bHttpDownloadRunning = false;

    reply->deleteLater();//要删除reply，但是不能在onFinished里直接delete，要调用deletelater;
    //pReply = nullptr;

}

void HTTPDownload::stop()
{
    if(m_bHttpDownloadRunning)
    {
        m_pNetWorkReply->abort();//响应终止
        m_bHttpDownloadRunning = false;
        qDebug() << "[HTTPDownload]停止下载1";
    }
    else
    {   //HTTPDownload();
        m_bHttpDownloadRunning = true;
        qDebug() << "[HTTPDownload]停止下载2";
    }
}


void HTTPDownload::onDownloadProgress(qint64 a, qint64 b)
{
    //file.write(reply->readAll());
    qDebug() << "[HTTPDownload]onDownloadProgress:" << a << "/" << b;
}

void HTTPDownload::onReplyError(QNetworkReply::NetworkError error)
{
    qCritical() << "[!HTTPDownload]onReplyError:" << error;
}

void HTTPDownload::onReplySslErrors(const QList<QSslError> &errors)
{
    qCritical() << "[!HTTPDownload]onReplySslErrors:" << errors;
}
